package com.vcommon.core.modules
{
import com.vcommon.core.loaderqueue.LoaderQueueEvent;
import com.vcommon.core.loaderqueue.adapter.LoaderAdapter;
import com.vcommon.core.logging.Tracer;

import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.Security;
import flash.system.SecurityDomain;
import flash.utils.ByteArray;

//--------------------------------------
//  Events
//--------------------------------------

/**
 *  Dispatched by the backing ModuleInfo if there was an error during
 *  module loading.
 *
 *  @eventType mx.events.ModuleEvent.ERROR
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="error", type="net.manaca.modules.ModuleEvent")]

/**
 *  Dispatched by the backing ModuleInfo at regular intervals
 *  while the module is being loaded.
 *
 *  @eventType net.manaca.modules.ModuleEvent.PROGRESS
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="progress", type="net.manaca.modules.ModuleEvent")]

/**
 *  Dispatched by the backing ModuleInfo once the module is sufficiently
 *  loaded to call the <code>IModuleInfo.factory()</code> method and the
 *  <code>IModuleFactory.create()</code> method.
 *
 *  @eventType net.manaca.modules.ModuleEvent.READY
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="ready", type="net.manaca.modules.ModuleEvent")]

/**
 *  Dispatched by the backing ModuleInfo when the module data is unloaded.
 *
 *  @eventType net.manaca.modules.ModuleEvent.UNLOAD
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="unload", type="net.manaca.modules.ModuleEvent")]

/**
 *  @private
 *  The ModuleInfo class encodes the loading state of a module.
 *  It isn't used directly, because there needs to be only one single
 *  ModuleInfo per URL, even if that URL is loaded multiple times,
 *  yet individual clients need their own dedicated events dispatched
 *  without re-dispatching to clients that already received their events.
 *  ModuleInfoProxy holds the public IModuleInfo implementation
 *  that can be externally manipulated.
 */
public class ModuleInfo extends AbstractModuleInfo implements IModuleInfo
{
    //==========================================================================
    //  Constructor
    //==========================================================================
    /**
     * @private
     */
    public function ModuleInfo(moduleName:String, skinDir:String)
    {
        super(moduleName, skinDir);
    }

    //==========================================================================
    //  Methods
    //==========================================================================
    /**
     * @private
     */
    override public function load(applicationDomain:ApplicationDomain=null,
                         securityDomain:SecurityDomain=null,
                         bytes:ByteArray=null,
                         level:uint = 0):void
    {
        super.load(applicationDomain, securityDomain, bytes, level);

        loaderContext.securityDomain = securityDomain;
        if (securityDomain == null && Security.sandboxType == Security.REMOTE)
        {
            loaderContext.securityDomain = SecurityDomain.currentDomain;
        }

        var url:String = moduleVO.url;
        var urlRequest:URLRequest = new URLRequest(url);

        mainLoader = new LoaderAdapter(loaderLevel, urlRequest,
            loaderContext);
        mainLoader.addEventListener(LoaderQueueEvent.TASK_COMPLETED,
            mainLoader_completedHandler);
        mainLoader.addEventListener(LoaderQueueEvent.TASK_ERROR,
            mainLoader_errorHandler);
        mainLoader.addEventListener(LoaderQueueEvent.TASK_PROGRESS,
            mainLoader_progressHandler);
        Tracer.debug("[Module] loading module : " + urlRequest.url);
        loaderQueue.addItem(mainLoader);
    }

    //==========================================================================
    //  Event Handlers
    //==========================================================================
    override protected function mainLoader_completedHandler(event:LoaderQueueEvent):void
    {
        var moduleEvent:ModuleEvent =
            new ModuleEvent(ModuleEvent.PROGRESS,
                event.bubbles, event.cancelable);
        moduleEvent.bytesLoaded =
            LoaderAdapter(mainLoader).adaptee.contentLoaderInfo.bytesLoaded;
        moduleEvent.bytesTotal = LoaderAdapter(mainLoader).adaptee.contentLoaderInfo.bytesTotal;
        dispatchEvent(moduleEvent);

        _applicationDomain =
            LoaderAdapter(mainLoader).adaptee.contentLoaderInfo.applicationDomain;
        _factoy = new ModuleFactory(applicationDomain, moduleVO);

        clearLoader();

        _ready = true;
        startLoadSkin();
    }
}
}
